﻿//========================================================= 
/**@file InterrupterCmdDriver.h
 * @brief 中断器命令
 * 
 * @date 2016-10-01   11:03:24
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_INTERRUPTERCMDDRIVER_H_
#define _LIBZHOUYB_INTERRUPTERCMDDRIVER_H_
//--------------------------------------------------------- 
#include "../CommonCmdDriver.h"
//--------------------------------------------------------- 
namespace zhou_yb {
namespace application {
namespace driver {
//--------------------------------------------------------- 
/// 支持记录中断次数的中断器
template<class TInterrupter>
class BreakpointInterrupter : public TInterrupter
{
protected:
    /// 中断次数计数
    volatile size_t _breakPoint;
public:
    BreakpointInterrupter() : TInterrupter() {}
    /// 设置中断器已中断(在中断点中处理)
    virtual void Breakout()
    {
        TInterrupter::Breakout();
        ++_breakPoint;
    }
    /// 重置 
    virtual bool Reset()
    {
        _breakPoint = 0;
        return TInterrupter::Reset();
    }
    inline size_t Breakpoint() const
    {
        return _breakPoint;
    }
};
//--------------------------------------------------------- 
/// 中断器命令
template<class TInterrupter>
class InterrupterCmdDriver : public CommandCollection
{
protected:
    Ref<IInterrupter> _refInterrupter;
    BreakpointInterrupter<TInterrupter> _interrupter;
public:
    InterrupterCmdDriver()
    {
        _refInterrupter = _interrupter;

        _RegisteCMD(InterrupterCmdDriver, Interrupt);
        _RegisteCMD(InterrupterCmdDriver, Cancel);
        _RegisteCMD(InterrupterCmdDriver, Implement);
        _RegisteCMD(InterrupterCmdDriver, InterruptReset);

        _RegisteInterfaceCMD(InterrupterCmdDriver, IInterrupter);
    }
    /**
     * @brief 中断等待操作
     * @date 2016-10-01 11:16
     * 
     * @param [in] Timeout : uint [default:0] 等待中断的最大超时时间(ms)
     * @warning 没有超时时间时,直接中断,不等待 Breakout
     *
     * @param [in] Interval : uint [default:DEV_OPERATOR_INTERVAL] 每次轮询的间隔时间(ms)
     */
    LC_CMD_METHOD(Interrupt)
    {
        string sTimeout;
        if(!arg.Get("Timeout", sTimeout))
            return _interrupter.Interrupt();

        uint timeoutMs = ArgConvert::FromString<uint>(sTimeout);
        uint intervalMs = arg["Interval"].To<uint>(DEV_OPERATOR_INTERVAL);

        return InterruptBehavior::Interrupt(_interrupter, timeoutMs, intervalMs);
    }
    /**
     * @brief 取消等待操作
     * @description 取消的原理:在Timeout超时时间内,检测到没有新的Breakout事件发生则表示所有的中断操作已执行完
     *
     * @date 2016-10-01 11:16
     * 
     * @param [in] Timeout : uint [default:500] 等待中断的最大超时时间(ms)     *
     * @param [in] Interval : uint [default:DEV_OPERATOR_INTERVAL] 每次轮询的间隔时间(ms)
     */
    LC_CMD_METHOD(Cancel)
    {
        uint timeoutMs = arg["Timeout"].To<uint>(DEV_CANCEL_TIMEOUT);
        uint intervalMs = arg["Interval"].To<uint>(DEV_OPERATOR_INTERVAL);
        
        bool isCancel = false;
        Timer timer;
        while(timer.Elapsed() < timeoutMs)
        {
            if(_interrupter.Interrupt())
            {
                isCancel = true;
                break;
            }
            Timer::Wait(intervalMs);
        }
        if(!isCancel)
        {
            _interrupter.Reset();
            return false;
        }

        isCancel = false;
        timer.Restart();

        size_t breakPoint = _interrupter.Breakpoint();
        size_t tmp = breakPoint;
        while(timer.Elapsed() < timeoutMs)
        {
            tmp = _interrupter.Breakpoint();
            if(tmp != breakPoint)
            {
                isCancel = true;
                timer.Restart();

                breakPoint = tmp;
            }
            Timer::Wait(intervalMs);
        }

        _interrupter.Reset();
        return isCancel;
    }
    /// 中断点
    LC_CMD_METHOD(Implement)
    {
        return InterruptBehavior::Implement(_interrupter);
    }
    /**
     * @brief 复位中断器
     * @date 2016-10-01 11:18
     */
    LC_CMD_METHOD(InterruptReset)
    {
        return _interrupter.Reset();
    }
    LC_CMD_INTERFACE_GETTER(IInterrupter, _refInterrupter);
};
//--------------------------------------------------------- 
} // nemespace driver
} // namespace application
} // namespace zhou_yb
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_INTERRUPTERCMDDRIVER_H_
//========================================================= 